package org.jsola.hr.service.impl;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.jsola.common.DateKit8;
import org.jsola.common.StrKit;
import org.jsola.core.Page;
import org.jsola.exception.ParamException;
import org.jsola.hr.common.ExampleKit;
import org.jsola.hr.common.ListKit;
import org.jsola.hr.constant.*;
import org.jsola.hr.dao.IEmpInfoDAO;
import org.jsola.hr.dao.ISalaryCalculateRuleDAO;
import org.jsola.hr.dto.*;
import org.jsola.hr.entity.ChannelDO;
import org.jsola.hr.entity.CheckInPeopleDO;
import org.jsola.hr.entity.EmpInfoDO;
import org.jsola.hr.entity.SalaryCalculateRuleDO;
import org.jsola.hr.entity.salary.*;
import org.jsola.hr.provider.ISalaryProviderService;
import org.jsola.hr.query.EmpInfoQuery;
import org.jsola.hr.query.SalaryCalculateRuleEmpInfoQuery;
import org.jsola.hr.query.SalaryCalculateRuleQuery;
import org.jsola.hr.service.*;
import org.jsola.hr.vo.*;
import org.jsola.orm.filter.Order;
import org.jsola.salary.vo.WorkTimeVO;
import org.jsola.user.core.TokenUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import tk.mybatis.mapper.entity.Example;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 工价计算规则
 *
 * @author zhr
 */
@Slf4j
@Service("hrSalaryCalculateRuleServiceImpl")
public class SalaryCalculateRuleServiceImpl implements ISalaryCalculateRuleService {

    @Autowired
    private ISalaryCalculateRuleDAO salaryCalculateRuleDAO;
    @Autowired
    private IEmpInfoService empInfoService;
    @Autowired
    private ICompanyService companyService;
    @Autowired
    private IEmpInfoDAO empInfoDAO;
    @Autowired
    private ICheckInPeopleService checkInPeopleService;
    @Autowired
    private IChannelService channelService;
    @Autowired
    private ISalaryProviderService salaryProviderService;

    @Autowired
    private IPersonalEventService personalEventService;

    @Autowired
    private ISalaryCalculateRuleGroupService salaryCalculateRuleGroupService;

    /**
     * 规则类型-工价计算
     */
    private static final Integer RULE_TYPE_SALARY = 1;

    /**
     * 规则类型-劳务费计算
     */
    private static final Integer RULE_TYPE_SERVICE = 2;

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public SalaryCalculateRuleVO save(SalaryCalculateRuleAddDTO salaryCalculateRuleAddDTO, TokenUser tokenUser) {
        // 修改来源是该规则组的 source 为空
        salaryCalculateRuleGroupService.setSourceIsNull(salaryCalculateRuleAddDTO.getSalaryCalculateRuleGroupId(), tokenUser);
        if (salaryCalculateRuleAddDTO.getHourAmountDouble() != null) {
            salaryCalculateRuleAddDTO.setHourAmount(Math.round(salaryCalculateRuleAddDTO.getHourAmountDouble() * 10000));
        }
        if (salaryCalculateRuleAddDTO.getSpecialCostDouble() != null) {
            salaryCalculateRuleAddDTO.setSpecialCost(Math.round(salaryCalculateRuleAddDTO.getSpecialCostDouble() * 10000));
        }
        check(salaryCalculateRuleAddDTO.to(SalaryCalculateRuleDO.class), tokenUser);
        // 转DO
        SalaryCalculateRuleDO salaryCalculateRuleDO = salaryCalculateRuleAddDTO.to(SalaryCalculateRuleDO.class);
        addSort(salaryCalculateRuleDO);
        // 保存
        salaryCalculateRuleDO = save(salaryCalculateRuleDO, tokenUser.getSiteId(), tokenUser.getUserId());
        return salaryCalculateRuleDO.to(SalaryCalculateRuleVO.class);
    }

    private void check(SalaryCalculateRuleDO newSalaryCalculateRuleDO, TokenUser tokenUser) {
        // 校验是否允许保存或编辑
        String groupId = newSalaryCalculateRuleDO.getSalaryCalculateRuleGroupId();
        if (StrKit.isEmpty(groupId)) {
            return;
        }
        TimeStart newTimeStart = new TimeStart();
        if (StrKit.isNotEmpty(newSalaryCalculateRuleDO.getTimeJson())) {
            newTimeStart = JSON.parseObject(newSalaryCalculateRuleDO.getTimeJson(), TimeStart.class);
        }
        // 根据分组id查询规则List
        List<SalaryCalculateRuleDO> salaryCalculateRuleDOList = this.selectByGroupId(groupId, tokenUser);
        if (CollectionUtils.isEmpty(salaryCalculateRuleDOList)) {
            return;
        }
        if (StrKit.isNotEmpty(newSalaryCalculateRuleDO.getId())) {
            salaryCalculateRuleDOList.removeIf(salaryCalculateRuleDO ->
                    newSalaryCalculateRuleDO.getId().equals(salaryCalculateRuleDO.getId()));
        }
        for (SalaryCalculateRuleDO salaryCalculateRuleDO : salaryCalculateRuleDOList) {
            String timeJson = salaryCalculateRuleDO.getTimeJson();
            if (StrKit.isEmpty(timeJson)) {
//                if (newTimeStart.getType() == null) {
//                    throw new ParamException("一个规则组中不允许添加两个长期规则");
//                } else {
//                    continue;
//                }
                throw new ParamException("该规则组中已有长期规则，无法添加其他规则!");
            }
            TimeStart timeStart = JSON.parseObject(timeJson, TimeStart.class);
            // 校验有的类型是否和新增的类型是否一样
            if (!timeStart.getType().equals(newTimeStart.getType())) {
                throw new ParamException("一个规则组中不允许添加两种时间类型(注：只能为一种，按时间/按日期)");
            }
            // 校验按时间排序范围是否一样
            if (timeStart.getType() == 1) {
                if (timeStart.getUnit() == null) {
                    throw new ParamException("时间单位不能为空");
                }
                if (!timeStart.getUnit().equals(newTimeStart.getUnit())) {
                    throw new ParamException("一个规则组内不允许添加两种时间单位(注：只能为一种，月/天/工时)");
                }
                // 校验时间是否覆盖:按时间
                if (timeStart.getEndNumber() == null && newTimeStart.getEndNumber() == null) {
                    throw new ParamException("该规则组中已有一个半长期规则，无法添加其他半长期规则!");
                }
                if (newTimeStart.getEndNumber() == null) {
                    newTimeStart.setEndNumber(new BigDecimal("876000"));
                }
                BigDecimal startNumber = timeStart.getStartNumber();
                BigDecimal endNumber = timeStart.getEndNumber() == null ? new BigDecimal("876000") : timeStart.getEndNumber();
                if (newTimeStart.getStartNumber().compareTo(startNumber) >= 0
                        && newTimeStart.getEndNumber().compareTo(endNumber) <= 0) {
                    throw new ParamException("时间不能重复");
                }
                if (newTimeStart.getStartNumber().compareTo(startNumber) >= 0
                        && newTimeStart.getStartNumber().compareTo(endNumber) <= 0) {
                    throw new ParamException("时间不能重复");
                }
                if (newTimeStart.getEndNumber().compareTo(startNumber) >= 0
                        && newTimeStart.getEndNumber().compareTo(endNumber) <= 0) {
                    throw new ParamException("时间不能重复");
                }
                if (startNumber.compareTo(newTimeStart.getStartNumber()) >= 0
                        && startNumber.compareTo(newTimeStart.getEndNumber()) <= 0) {
                    throw new ParamException("时间不能重复");
                }
                if (endNumber.compareTo(newTimeStart.getStartNumber()) >= 0
                        && endNumber.compareTo(newTimeStart.getEndNumber()) <= 0) {
                    throw new ParamException("时间不能重复");
                }
            } else {
                if (newTimeStart.getEndTime() == null) {
                    newTimeStart.setEndTime("2100-01-01");
                }
                // 校验时间是否覆盖:按日期
                String startTime = timeStart.getStartTime();
                String endTime = timeStart.getEndTime() == null ? "2100-01-01" : timeStart.getEndTime();
                if (DateKit8.parseDate(newTimeStart.getStartTime()).getTime() >= DateKit8.parseDate(startTime).getTime()
                        && DateKit8.parseDate(newTimeStart.getStartTime()).getTime() <= DateKit8.parseDate(endTime).getTime()) {
                    throw new ParamException("时间不能重复");
                }
                if (DateKit8.parseDate(newTimeStart.getEndTime()).getTime() >= DateKit8.parseDate(startTime).getTime()
                        && DateKit8.parseDate(newTimeStart.getEndTime()).getTime() <= DateKit8.parseDate(endTime).getTime()) {
                    throw new ParamException("时间不能重复");
                }
                if (DateKit8.parseDate(startTime).getTime() >= DateKit8.parseDate(newTimeStart.getStartTime()).getTime()
                        && DateKit8.parseDate(startTime).getTime() <= DateKit8.parseDate(newTimeStart.getEndTime()).getTime()) {
                    throw new ParamException("时间不能重复");
                }
                if (DateKit8.parseDate(endTime).getTime() >= DateKit8.parseDate(newTimeStart.getStartTime()).getTime()
                        && DateKit8.parseDate(endTime).getTime() <= DateKit8.parseDate(newTimeStart.getEndTime()).getTime()) {
                    throw new ParamException("时间不能重复");
                }
            }
        }
    }

    private void addSort(SalaryCalculateRuleDO newSalaryCalculateRuleDO) {
        // 添加排序值
        if (StrKit.isEmpty(newSalaryCalculateRuleDO.getTimeJson())) {
            // 长期规则排序为30000000
            newSalaryCalculateRuleDO.setSort(30000000);
            return;
        }
        TimeStart timeStart = JSON.parseObject(newSalaryCalculateRuleDO.getTimeJson(), TimeStart.class);
        if (timeStart.getType() == 1) {
            newSalaryCalculateRuleDO.setSort(timeStart.getStartNumber().intValue());
        } else {
            String startTime = timeStart.getStartTime();
            String[] sortStartTime = startTime.split("-");
            int sort = Integer.parseInt(sortStartTime[0] + sortStartTime[1] + sortStartTime[2]);
            newSalaryCalculateRuleDO.setSort(sort);
        }
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int update(SalaryCalculateRuleUpdateDTO salaryCalculateRuleUpdateDTO, TokenUser tokenUser) {
        // 修改来源是该规则组的 source 为空
        salaryCalculateRuleGroupService.setSourceIsNull(salaryCalculateRuleUpdateDTO.getSalaryCalculateRuleGroupId(), tokenUser);
        if (salaryCalculateRuleUpdateDTO.getHourAmountDouble() != null) {
            salaryCalculateRuleUpdateDTO.setHourAmount(Math.round(salaryCalculateRuleUpdateDTO.getHourAmountDouble() * 10000));
        }
        if (salaryCalculateRuleUpdateDTO.getSpecialCostDouble() != null) {
            salaryCalculateRuleUpdateDTO.setSpecialCost(Math.round(salaryCalculateRuleUpdateDTO.getSpecialCostDouble() * 10000));
        }
        check(salaryCalculateRuleUpdateDTO.to(SalaryCalculateRuleDO.class), tokenUser);

        //转DO
        SalaryCalculateRuleDO salaryCalculateRuleDO = salaryCalculateRuleUpdateDTO.to(SalaryCalculateRuleDO.class);
        addSort(salaryCalculateRuleDO);
        //根据主键更新，只更新非null值
        return updateByIdSelective(salaryCalculateRuleDO, tokenUser.getSiteId(), tokenUser.getUserId());
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int deleteByIds(TokenUser tokenUser, String... salaryCalculateRuleIds) {
        // 删除限制
        for (String salaryCalculateRuleId : salaryCalculateRuleIds) {
            SalaryCalculateRuleDO salaryCalculateRuleDO = this.selectDOById(salaryCalculateRuleId, tokenUser.getSiteId());
            ParamException.notNull(salaryCalculateRuleDO, "规则不存在或已被删除，请稍后重试");
            // 修改来源是该规则组的 source 为空
            salaryCalculateRuleGroupService.setSourceIsNull(salaryCalculateRuleDO.getSalaryCalculateRuleGroupId(), tokenUser);
            List<EmpInfoListVO> empInfoListVOList = selectEmpInfoListVOByRuleTypeAndSalaryCalculateRuleId(
                    salaryCalculateRuleDO.getRuleType(), salaryCalculateRuleId, tokenUser);
            ParamException.isTrue(CollectionUtils.isEmpty(empInfoListVOList),
                    "规则" + salaryCalculateRuleDO.getName() + "被使用中，无法删除，请先删除该规则的使用人员!");
        }
        return logicalDeleteByIds(tokenUser.getSiteId(), tokenUser.getUserId(), (Object[]) salaryCalculateRuleIds);
    }


    @Override
    public SalaryCalculateRuleVO selectById(String salaryCalculateRuleId, String siteId) {
        SalaryCalculateRuleDO salaryCalculateRuleDO = selectDOById(salaryCalculateRuleId, siteId);
        if (salaryCalculateRuleDO == null) {
            return null;
        }
        SalaryCalculateRuleVO salaryCalculateRuleVO = salaryCalculateRuleDO.to(SalaryCalculateRuleVO.class);
        salaryCalculateRuleVO.setHourAmountDouble(salaryCalculateRuleDO.getHourAmount() == null ?
                0 : salaryCalculateRuleDO.getHourAmount().doubleValue() / 10000);
        salaryCalculateRuleVO.setSpecialCostDouble(salaryCalculateRuleDO.getSpecialCost() == null ?
                0 : salaryCalculateRuleDO.getSpecialCost().doubleValue() / 10000);
        return salaryCalculateRuleVO;
    }

    @Override
    public List<SalaryCalculateRuleListVO> select(SalaryCalculateRuleQuery salaryCalculateRuleQuery, String siteId) {
        List<SalaryCalculateRuleDO> salaryCalculateRuleDOList = selectDO(salaryCalculateRuleQuery, siteId);
        if (CollectionUtils.isEmpty(salaryCalculateRuleDOList)) {
            return salaryCalculateRuleDOList == null ? null : new ArrayList<>();
        }
        List<SalaryCalculateRuleListVO> salaryCalculateRuleListVOList = salaryCalculateRuleDOList.stream()
                .map(salaryCalculateRuleDO -> salaryCalculateRuleDO.to(SalaryCalculateRuleListVO.class))
                .collect(Collectors.toList());
        salaryCalculateRuleListVOList.forEach(salaryCalculateRuleListVO -> {
            salaryCalculateRuleListVO.setHourAmountDouble(salaryCalculateRuleListVO.getHourAmount() == null ?
                    0 : salaryCalculateRuleListVO.getHourAmount().doubleValue() / 10000);
            salaryCalculateRuleListVO.setSpecialCostDouble(salaryCalculateRuleListVO.getSpecialCost() == null ?
                    0 : salaryCalculateRuleListVO.getSpecialCost().doubleValue() / 10000);
        });
        return salaryCalculateRuleListVOList;
    }

    @Override
    public int selectCount(SalaryCalculateRuleQuery salaryCalculateRuleQuery, String siteId) {
        Example example = buildExample(salaryCalculateRuleQuery, siteId);
        return salaryCalculateRuleDAO.selectCountByExample(example);
    }

    @Override
    public Page<SalaryCalculateRuleListVO> selectPage(SalaryCalculateRuleQuery salaryCalculateRuleQuery, String siteId) {
        Example example = buildExample(salaryCalculateRuleQuery, siteId);
        Page<SalaryCalculateRuleDO> page = salaryCalculateRuleDAO.selectPageByExample(example,
                salaryCalculateRuleQuery.getPageNo(),
                salaryCalculateRuleQuery.getPageSize());
        Page<SalaryCalculateRuleListVO> returnPage = page.to(SalaryCalculateRuleListVO.class);
        returnPage.getEntities().forEach(salaryCalculateRuleListVO -> {
            salaryCalculateRuleListVO.setHourAmountDouble(salaryCalculateRuleListVO.getHourAmount() == null ?
                    0 : salaryCalculateRuleListVO.getHourAmount().doubleValue() / 10000);
            salaryCalculateRuleListVO.setSpecialCostDouble(salaryCalculateRuleListVO.getSpecialCost() == null ?
                    0 : salaryCalculateRuleListVO.getSpecialCost().doubleValue() / 10000);
        });
        return returnPage;
    }

    @Override
    public SalaryCalculateRuleDO selectDOById(String salaryCalculateRuleId, String siteId) {
        return listById(salaryCalculateRuleId, siteId);
    }

    @Override
    public List<SalaryCalculateRuleDO> selectDOByIds(List<String> salaryCalculateRuleIds, String siteId) {
        if (CollectionUtils.isEmpty(salaryCalculateRuleIds)) {
            return new ArrayList<>();
        }
        Example example = new Example(SalaryCalculateRuleDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId)
                .andIn("id", salaryCalculateRuleIds);
        return salaryCalculateRuleDAO.selectByExample(example);
    }

    @Override
    public List<SalaryCalculateRuleDO> selectDO(SalaryCalculateRuleQuery salaryCalculateRuleQuery, String siteId) {
        Example example = buildExample(salaryCalculateRuleQuery, siteId);
        return salaryCalculateRuleDAO.selectByExample(example);
    }

    @Override
    public void setUsePeopleNumber(SalaryCalculateRuleListVO salaryCalculateRuleListVO, TokenUser tokenUser) {
        // 根据规则id查询员工信息表里使用的人数
        List<EmpInfoListVO> empInfoListVOList = selectEmpInfoListVOByRuleTypeAndSalaryCalculateRuleId(salaryCalculateRuleListVO.getRuleType(),
                salaryCalculateRuleListVO.getId(), tokenUser);
        salaryCalculateRuleListVO.setUsePeopleNumber(empInfoListVOList.size());
    }

    @Override
    public Page<EmpInfoVO> selectEmpInfoVoBySalaryCalculateRuleId(SalaryCalculateRuleEmpInfoQuery salaryCalculateRuleEmpInfoQuery, TokenUser tokenUser) {
        Page<EmpInfoVO> page = new Page<>(salaryCalculateRuleEmpInfoQuery.getPageSize(), salaryCalculateRuleEmpInfoQuery.getPageNo());
        // 查询规则
        String salaryCalculateRuleId = salaryCalculateRuleEmpInfoQuery.getSalaryCalculateRuleId();
        String nameOrIdCard = salaryCalculateRuleEmpInfoQuery.getNameOrIdCard();
        SalaryCalculateRuleVO salaryCalculateRuleVO = this.selectById(salaryCalculateRuleId, tokenUser.getSiteId());
        ParamException.notNull(salaryCalculateRuleVO, "根据规则id没有找到该规则信息!");
        Integer ruleType = salaryCalculateRuleVO.getRuleType();
        // 根据条件查询员工信息
        Example example = new Example(EmpInfoDO.class);
        if (ruleType.equals(CalculatePayConstant.RULE_TYPE_COMMISSION)) {
            example.and().andEqualTo("serviceFeeRuleId", salaryCalculateRuleId);
        } else {
            example.and().andEqualTo("salaryRuleId", salaryCalculateRuleId);
        }
        if (StrKit.isNotEmpty(nameOrIdCard)) {
            example.and()
                    .orLike("name", "%" + nameOrIdCard + "%")
                    .orLike("idCard", "%" + nameOrIdCard + "%");
        }
        example.and()
                .andEqualTo("siteId", tokenUser.getSiteId())
                .andEqualTo("valid", true);
        List<EmpInfoDO> empInfoDOList = empInfoDAO.selectByExample(example);
        // 过滤重复及离职的员工
        // 根据手机号过滤
        empInfoDOList = empInfoDOList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() ->
                new TreeSet<>(Comparator.comparing(EmpInfoDO::getPhone))), ArrayList::new));
        // 过滤掉离职的员工信息
        empInfoDOList.removeIf(empInfoDO -> EmpInfoStatus.HAS_QUIT.getValue().equals(empInfoDO.getStatus()));
        if (CollectionUtils.isEmpty(empInfoDOList)) {
            return page;
        }
        // 添加用工单位名称
        empInfoDOList.forEach(empInfoDO -> {
            CompanyVO companyVO = companyService.selectBaseCompanyById(empInfoDO.getCompanyId(), tokenUser.getSiteId());
            empInfoDO.setWorkingUnitName(companyVO != null ? companyVO.getName() : "查询不到该公司信息");
        });
        List<EmpInfoVO> empInfoVOList = empInfoDOList.stream().map(empInfoDO -> empInfoDO.to(EmpInfoVO.class)).collect(Collectors.toList());
        // 添加渠道信息
        empInfoVOList.forEach(empInfoVO -> {
            // 根据手机号查询预登记人员
            CheckInPeopleDO checkInPeopleDO = checkInPeopleService.selectByPhone(empInfoVO.getPhone(), tokenUser.getSiteId());
            if (Objects.nonNull(checkInPeopleDO)) {
                empInfoVO.setChannelVO(channelService.selectById(checkInPeopleDO.getChannelId(), tokenUser.getSiteId()));
            }
        });

        // 构建page
        page.setEntityCount(empInfoVOList.size());
        int size = salaryCalculateRuleEmpInfoQuery.getPageSize();
        int no = salaryCalculateRuleEmpInfoQuery.getPageNo();
        if (empInfoVOList.size() > no * size) {
            empInfoVOList = empInfoVOList.subList((no - 1) * size, no * size);
        } else if (empInfoVOList.size() > (no - 1) * size) {
            empInfoVOList = empInfoVOList.subList((no - 1) * size, empInfoVOList.size());
        } else if (empInfoVOList.size() > size) {
            empInfoVOList = empInfoVOList.subList(0, size);
        }
        page.setEntities(empInfoVOList);
        return page;
    }


    @Override
    public EmpInfoSalaryVO selectRuleByEmpId(String empId, TokenUser tokenUser) {
        EmpInfoVO empInfoVO = empInfoService.selectById(empId, tokenUser.getSiteId());
        // 工价计算规则id
        String salaryRuleId = empInfoVO.getSalaryRuleId();
        // 劳务费计算规则id
        String serviceFeeRuleId = empInfoVO.getServiceFeeRuleId();

        EmpInfoSalaryVO empInfoSalaryVO = new EmpInfoSalaryVO();
        empInfoSalaryVO.setId(empId);
        empInfoSalaryVO.setName(empInfoVO.getName());
        empInfoSalaryVO.setSalaryRuleId(salaryRuleId);
        empInfoSalaryVO.setServiceFeeRuleId(serviceFeeRuleId);
        SalaryCalculateRuleGroupVO salaryRule = salaryCalculateRuleGroupService.selectById(salaryRuleId, tokenUser.getSiteId());
        SalaryCalculateRuleGroupVO serviceFeeRule = salaryCalculateRuleGroupService.selectById(serviceFeeRuleId, tokenUser.getSiteId());
        empInfoSalaryVO.setSalaryRule(salaryRule);
        empInfoSalaryVO.setServiceFeeRule(serviceFeeRule);
        return empInfoSalaryVO;
    }

    @Override
    public Page<EmpInfoSalaryVO> selectOutsourceSalary(SalaryCalculateRuleEmpInfoQuery query,
                                                       TokenUser tokenUser) {
        String siteId = tokenUser.getSiteId();
        // 查询员工性质为外包的员工
        Page<EmpInfoVO> empInfoVOPage1 = empInfoService.pageByCompanyId(query, tokenUser);
        Page<EmpInfoSalaryVO> empInfoVOPage = empInfoVOPage1.to(EmpInfoSalaryVO.class);
        List<EmpInfoSalaryVO> empInfoSalaryVOS = empInfoVOPage.getEntities();

        // 薪资规则id
        List<String> salaryRuleList = empInfoSalaryVOS.stream()
                .map(EmpInfoSalaryVO::getSalaryRuleId)
                .collect(Collectors.toList());
        // 劳务费规则id
        List<String> serviceFeeRuleList = empInfoSalaryVOS.stream()
                .map(EmpInfoSalaryVO::getServiceFeeRuleId).filter(Objects::nonNull)
                .collect(Collectors.toList());

        // 渠道id
        List<String> ruleIdList = new ArrayList<>();
        ruleIdList.addAll(salaryRuleList);
        ruleIdList.addAll(serviceFeeRuleList);
        List<SalaryCalculateRuleGroupVO> salaryCalculateRuleGroupVOList = new ArrayList<>();
        for (String salaryCalculateRuleGroupId : ruleIdList) {
            SalaryCalculateRuleGroupVO salaryCalculateRuleGroupVO = salaryCalculateRuleGroupService
                    .selectById(salaryCalculateRuleGroupId, tokenUser.getSiteId());
            if (Objects.nonNull(salaryCalculateRuleGroupVO)) {
                salaryCalculateRuleGroupVOList.add(salaryCalculateRuleGroupVO);
            }
        }
        // 规则id - 工价计算规则 Map
        Map<String, SalaryCalculateRuleGroupVO> ruleVOMap = salaryCalculateRuleGroupVOList.parallelStream()
                .collect(Collectors.toMap(SalaryCalculateRuleGroupVO::getId, v -> v, (v1, v2) -> v1));
        setValue(empInfoSalaryVOS, ruleVOMap, tokenUser);
        empInfoVOPage.setEntities(empInfoSalaryVOS);
        return empInfoVOPage;
    }


    /**
     * 写入员工工价规则,工时
     */
    private void setValue(List<EmpInfoSalaryVO> empInfoSalaryVOS, Map<String, SalaryCalculateRuleGroupVO> ruleDOMap,
                          TokenUser tokenUser) {
        // 员工id
        List<String> empIdList = empInfoSalaryVOS.stream()
                .map(EmpInfoSalaryVO::getId)
                .collect(Collectors.toList());
        // 员工id-工时 Map
        Map<String, WorkTimeVO> empIdWorkTimeVOMap = getWorkTime(empIdList, tokenUser);
        for (EmpInfoSalaryVO entity : empInfoSalaryVOS) {
            // 薪资规则id
            String salaryRuleId = entity.getSalaryRuleId();
            // 劳务费规则id
            String serviceFeeRuleId = entity.getServiceFeeRuleId();
            // 员工id
            String empId = entity.getId();
            if (StrKit.isNotEmpty(salaryRuleId)) {
                if (ruleDOMap.containsKey(salaryRuleId)) {
                    SalaryCalculateRuleGroupVO ruleVO = ruleDOMap.get(salaryRuleId);
//                    if (null != ruleVO && null != ruleVO.getHourAmount()) {
//                        ruleVO.setHourAmountDouble(Double.valueOf(ruleVO.getHourAmount()) / 10000);
//                    }
                    entity.setSalaryRule(ruleVO);
                }
            }
            if (StrKit.isNotEmpty(serviceFeeRuleId)) {
                if (ruleDOMap.containsKey(serviceFeeRuleId)) {
                    SalaryCalculateRuleGroupVO calculateRuleVO = ruleDOMap.get(serviceFeeRuleId);
                    entity.setServiceFeeRule(calculateRuleVO);
                }
            }
            // 设置渠道名称名称
            if (!StringUtils.isEmpty(entity.getChannelId())) {
                ChannelDO channel = channelService.selectDOById(entity.getChannelId(), tokenUser.getSiteId());
                if (channel != null) {
                    entity.setChannelName(channel.getName());
                }
            }
            if (empIdWorkTimeVOMap.containsKey(empId)) {
                WorkTimeVO workTimeVO = empIdWorkTimeVOMap.get(empId);
                if (null != workTimeVO) {
                    entity.setWorkHour(workTimeVO.getWorkTime());
                    entity.setWorkDay(workTimeVO.getWorkDay());
                }
            } else {
                entity.setWorkHour(0F);
                entity.setWorkDay(0F);
            }
        }
    }

    /**
     * 获取员工截止到上个月的累计工时
     */
    private Map<String, WorkTimeVO> getWorkTime(List<String> empIdList, TokenUser tokenUser) {
        Calendar calendar = Calendar.getInstance();
        int yearly = calendar.get(Calendar.YEAR);
        int monthly = calendar.get(Calendar.MONTH) + 1;
        List<WorkTimeVO> lastMonthWorkTime = salaryProviderService.getLastMonthWorkTime(empIdList, yearly, monthly,
                tokenUser);
        return lastMonthWorkTime.parallelStream()
                .collect(Collectors.toMap(WorkTimeVO::getEmpId, v -> v, (v1, v2) -> v1));

    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public EmpInfoSalaryVO saveSalaryCalculateRule(EmpRuleAddDTO empRuleAddDTO, TokenUser tokenUser) {
        String empId = empRuleAddDTO.getEmpId();
        EmpInfoDO empInfoDO = empInfoService.selectDOById(empId, tokenUser.getSiteId());
        // 之前的工价规则
        String salaryRuleId = empInfoDO.getSalaryRuleId();
        // 之前的劳务费规则
        String serviceFeeRuleId = empInfoDO.getServiceFeeRuleId();

        EmpInfoSalaryVO empInfoSalaryVO = new EmpInfoSalaryVO();
        SalaryRuleDTO salaryRuleDTO = new SalaryRuleDTO();
        salaryRuleDTO.setEmpId(empRuleAddDTO.getEmpId());
        salaryRuleDTO.setSalaryRuleId(empRuleAddDTO.getSalaryRuleId());
        salaryRuleDTO.setServiceFeeRuleId(empRuleAddDTO.getServiceFeeRuleId());
        empInfoSalaryVO.setSalaryRuleId(empRuleAddDTO.getSalaryRuleId());
        empInfoSalaryVO.setServiceFeeRuleId(empRuleAddDTO.getServiceFeeRuleId());
        SalaryCalculateRuleAddDTO salaryRuleAddDTO = empRuleAddDTO.getSalaryRuleAddDTO();
        SalaryCalculateRuleAddDTO serviceFeeRuleAddDTO = empRuleAddDTO.getServiceFeeRuleAddDTO();
        // 校验薪资规则
        if (Objects.nonNull(salaryRuleAddDTO)) {
            if (checkRule(empRuleAddDTO.getSalaryRuleId(), empRuleAddDTO.getSalaryRuleAddDTO(), RULE_TYPE_SALARY, tokenUser)) {
                salaryRuleAddDTO.setHourAmount(Math.round(salaryRuleAddDTO.getHourAmountDouble() * 10000));
                SalaryCalculateRuleVO salaryCalculateRuleVO = saveRule(salaryRuleAddDTO,
                        CalculatePayConstant.RULE_TYPE_MAN_HOUR, tokenUser);

//                empInfoSalaryVO.setSalaryRule(salaryCalculateRuleVO);
                salaryRuleDTO.setSalaryRuleId(salaryCalculateRuleVO.getId());
                empInfoSalaryVO.setSalaryRuleId(salaryCalculateRuleVO.getId());
            }
        }
        // 校验劳务费规则,不同则创建新规则
        if (Objects.nonNull(serviceFeeRuleAddDTO)) {
            if (checkRule(empRuleAddDTO.getServiceFeeRuleId(), empRuleAddDTO.getServiceFeeRuleAddDTO(), RULE_TYPE_SERVICE, tokenUser)) {
                serviceFeeRuleAddDTO.setHourAmount(Math.round(serviceFeeRuleAddDTO.getHourAmountDouble() * 10000));
                SalaryCalculateRuleVO salaryCalculateRuleVO = saveRule(serviceFeeRuleAddDTO,
                        CalculatePayConstant.RULE_TYPE_COMMISSION, tokenUser);

//                empInfoSalaryVO.setServiceFeeRule(salaryCalculateRuleVO);
                salaryRuleDTO.setServiceFeeRuleId(salaryCalculateRuleVO.getId());
                empInfoSalaryVO.setServiceFeeRuleId(salaryCalculateRuleVO.getId());
            }
        }
        // 本次的工价规则
        String salaryRuleIdNow = salaryRuleDTO.getSalaryRuleId();
        // 本次的劳务费规则
        String serviceFeeRuleIdNow = salaryRuleDTO.getServiceFeeRuleId();
        // 将null改为"",只要上次的值和本次不一致就写入员工档案
        salaryRuleId = salaryRuleId == null ? "" : salaryRuleId;
        serviceFeeRuleId = serviceFeeRuleId == null ? "" : serviceFeeRuleId;

        if (!Objects.equals(salaryRuleId, salaryRuleIdNow)) {
            savePersonalEvent(empRuleAddDTO.getEmpId(), "由【" + tokenUser.getUserName() + "】办理工价规则",
                    PersonalEventEnum.SALARY_RULE.getValue(), PersonalEventEnum.SALARY_RULE.getDesc(), tokenUser);
        }
        if (!Objects.equals(serviceFeeRuleId, serviceFeeRuleIdNow)) {
            savePersonalEvent(empRuleAddDTO.getEmpId(), "由【" + tokenUser.getUserName() + "】办理招工劳务费规则",
                    PersonalEventEnum.SERVICE_RULE.getValue(), PersonalEventEnum.SERVICE_RULE.getDesc(), tokenUser);
        }
        //  删除员工定薪信息
        salaryProviderService.deleteFixedInfoByEmpId(empId, tokenUser);
        empInfoService.updateSalaryRule(salaryRuleDTO, tokenUser);
        return empInfoSalaryVO;
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public Integer batchSaveSalaryCalculateRule(EmpRuleBatchAddDTO empRuleBatchAddDTO, TokenUser tokenUser) {
        List<String> empIdList = empRuleBatchAddDTO.getEmpIdList();
        // 工价规则id
        String salaryRuleId = empRuleBatchAddDTO.getSalaryRuleId();
        // 劳务费规则id
        String serviceFeeRuleId = empRuleBatchAddDTO.getServiceFeeRuleId();
        for (String empId : empIdList) {
            updateEmpInfo(empId, salaryRuleId, serviceFeeRuleId, tokenUser);
        }
        return empIdList.size();
    }

    /**
     * 更新员工工价规则id，劳务费规则id
     *
     * @param empId            员工id
     * @param salaryRuleId     工价规则id
     * @param serviceFeeRuleId 劳务费规则id
     * @param tokenUser        当前用户
     */
    private void updateEmpInfo(String empId, String salaryRuleId, String serviceFeeRuleId, TokenUser tokenUser) {
        EmpInfoUpdateDTO updateDTO = new EmpInfoUpdateDTO();
        updateDTO.setId(empId);
        updateDTO.setSalaryRuleId(salaryRuleId);
        updateDTO.setServiceFeeRuleId(serviceFeeRuleId);
        updateDTO.setSalaryType(SalaryFileTypeEnum.WORK_SALARY.getValue());
        if (salaryRuleId != null) {
            savePersonalEvent(empId, "由【" + tokenUser.getUserName() + "】办理工价规则",
                    PersonalEventEnum.SALARY_RULE.getValue(), PersonalEventEnum.SALARY_RULE.getDesc(), tokenUser);
        }
        if (serviceFeeRuleId != null) {
            savePersonalEvent(empId, "由【" + tokenUser.getUserName() + "】办理招工劳务费规则",
                    PersonalEventEnum.SERVICE_RULE.getValue(), PersonalEventEnum.SERVICE_RULE.getDesc(), tokenUser);
        }
        empInfoService.update(updateDTO, tokenUser);
    }

    @Override
    public List<SalaryCalculateRuleDO> selectByGroupId(String groupId, TokenUser tokenUser) {
        if (StrKit.isEmpty(groupId)) {
            return new ArrayList<>();
        }
        Example example = new Example(SalaryCalculateRuleDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", tokenUser.getSiteId())
                .andEqualTo("salaryCalculateRuleGroupId", groupId);
        example.setOrderByClause("sort ASC");
        return salaryCalculateRuleDAO.selectByExample(example);
    }

    @Override
    public void setReturnValueByListVO(SalaryCalculateRuleListVO salaryCalculateRuleListVO) {
        // 时间展示字符串
        String timeShow = buildTimeShow(salaryCalculateRuleListVO);
        salaryCalculateRuleListVO.setTimeShow(timeShow);

        // 构建红包规则List
        List<RedPacketRule> redPacketRuleList = new ArrayList<>();
        RedPacketRule normalPacketRule = null;
        RedPacketRule leaveRedPacketRule = null;
        if (StrKit.isNotEmpty(salaryCalculateRuleListVO.getRedPacketRule())) {
            redPacketRuleList = JSON.parseArray(salaryCalculateRuleListVO.getRedPacketRule(), RedPacketRule.class);
        }
        for (RedPacketRule redPacketRule : redPacketRuleList) {
            if (CalculatePayConstant.CALCULATE_TYPE_NORMAL.equals(redPacketRule.getCalculateType())) {
                normalPacketRule = redPacketRule;
            } else {
                leaveRedPacketRule = redPacketRule;
            }
        }

        // 基础规则展示字符串
        String hourAmountRuleShow = buildHourAmountRuleShow(salaryCalculateRuleListVO, normalPacketRule);
        salaryCalculateRuleListVO.setHourAmountRuleShow(hourAmountRuleShow);

        // 离职规则展示字符串
        String leaveOfficeRuleShow = buildLeaveOfficeRuleShow(salaryCalculateRuleListVO, leaveRedPacketRule);
        salaryCalculateRuleListVO.setLeaveOfficeRuleShow(leaveOfficeRuleShow);

    }

    /**
     * 构造时间展示字符串
     *
     * @param salaryCalculateRuleListVO 规则信息
     * @return 时间展示字符串
     */
    private String buildTimeShow(SalaryCalculateRuleListVO salaryCalculateRuleListVO) {
        StringBuilder timeShow = new StringBuilder();
        if (CalculatePayConstant.TIME_TYPE_LIMIT.equals(salaryCalculateRuleListVO.getTimeType())) {
            TimeStart timeStart = JSON.parseObject(salaryCalculateRuleListVO.getTimeJson(), TimeStart.class);
            timeShow.append("限时-");
            if (CalculatePayConstant.TIME_START_TYPE_Time.equals(timeStart.getType())) {
                String unitString = timeStart.getUnit() == null ?
                        "未设置单位" : timeStart.getUnit() == 1 ?
                        "月" : timeStart.getUnit() == 2 ? "天" : "工时";
                timeShow.append("按时间-入职后第").append(timeStart.getStartNumber())
                        .append("~").append(timeStart.getEndNumber()).append(unitString);
            } else {
                timeShow.append("按日期-").append(timeStart.getStartTime()).append("~").append(timeStart.getEndTime());
            }
        } else if (CalculatePayConstant.TIME_TYPE_LONG_LIMIT.equals(salaryCalculateRuleListVO.getTimeType())) {
            TimeStart timeStart = JSON.parseObject(salaryCalculateRuleListVO.getTimeJson(), TimeStart.class);
            timeShow.append("半长期-");
            if (CalculatePayConstant.TIME_START_TYPE_Time.equals(timeStart.getType())) {
                String unitString = timeStart.getUnit() == null ?
                        "未设置单位" : timeStart.getUnit() == 1 ?
                        "月" : timeStart.getUnit() == 2 ? "天" : "工时";
                timeShow.append("按时间-始于第").append(timeStart.getStartNumber()).append(unitString);
            } else {
                timeShow.append("按日期-始于").append(timeStart.getStartTime());
            }
        } else {
            timeShow.append("长期");
        }
        return timeShow.toString();
    }

    /**
     * 构造基础规则展示字符串
     *
     * @param salaryCalculateRuleListVO 规则信息
     * @param normalPacketRule          基础规则的红包信息
     * @return 基础规则展示字符串
     */
    private String buildHourAmountRuleShow(SalaryCalculateRuleListVO salaryCalculateRuleListVO,
                                           RedPacketRule normalPacketRule) {
        // 判断工价规则还是劳务费规则(1:工价规则 2：劳务费规则)
        Integer ruleType = salaryCalculateRuleListVO.getRuleType();
        // 构造基础规则展示字符串
        StringBuilder hourAmountRuleShow = new StringBuilder();
        List<HourAmountRule> hourAmountRuleList = new ArrayList<>();
        if (StrKit.isNotEmpty(salaryCalculateRuleListVO.getHourAmountRule())) {
            hourAmountRuleList = JSON.parseArray(salaryCalculateRuleListVO.getHourAmountRule(), HourAmountRule.class);
        }
        if (!CollectionUtils.isEmpty(hourAmountRuleList) && CalculatePayConstant.RULE_TYPE_MAN_HOUR.equals(ruleType)) {
            String showType = CalculatePayConstant.SHOW_TYPE_MAN_DAY.equals(salaryCalculateRuleListVO.getShowType()) ?
                    "计天制-" : "计时制-";
            String unit = CalculatePayConstant.SHOW_TYPE_MAN_DAY.equals(salaryCalculateRuleListVO.getShowType()) ?
                    "天" : "工时";
            hourAmountRuleShow.append("工价计算—").append(showType).append("工价")
                    .append(hourAmountRuleList.get(0).getHourAmount()).append("元/").append(unit).append("。");
        } else if (!CollectionUtils.isEmpty(hourAmountRuleList) && CalculatePayConstant.RULE_TYPE_COMMISSION.equals(ruleType)) {
            String showType = CalculatePayConstant.SHOW_TYPE_MAN_DAY.equals(salaryCalculateRuleListVO.getShowType()) ?
                    "按天分润-" : CalculatePayConstant.SHOW_TYPE_MAN_HOUR.equals(salaryCalculateRuleListVO.getShowType()) ?
                    "工时分润-" : "比例分润-";
            String unit = CalculatePayConstant.SHOW_TYPE_MAN_DAY.equals(salaryCalculateRuleListVO.getShowType()) ?
                    "元/天" : CalculatePayConstant.SHOW_TYPE_MAN_HOUR.equals(salaryCalculateRuleListVO.getShowType()) ?
                    "元/工时" : "%工人实发工资";
            hourAmountRuleShow.append("渠道分润—").append(showType).append("分润")
                    .append(hourAmountRuleList.get(0).getHourAmount()).append(unit).append("。");
        }
        if (Objects.nonNull(normalPacketRule)) {
            String unit = CalculatePayConstant.UNIT_MONTH.equals(normalPacketRule.getUnits()) ?
                    "月" : CalculatePayConstant.UNIT_DAY.equals(normalPacketRule.getUnits()) ?
                    "天" : "工时";
            hourAmountRuleShow.append("红包-每满").append(normalPacketRule.getNumber()).append(unit)
                    .append("发放").append(normalPacketRule.getRedPacketAmount()).append("红包。");
        }
        return hourAmountRuleShow.toString();
    }

    /**
     * 构造离职规则展示字符串
     *
     * @param salaryCalculateRuleListVO 规则信息
     * @param leaveRedPacketRule        离职规则的红包信息
     * @return 基础规则展示字符串
     */
    private String buildLeaveOfficeRuleShow(SalaryCalculateRuleListVO salaryCalculateRuleListVO,
                                            RedPacketRule leaveRedPacketRule) {
        StringBuilder leaveOfficeRuleShow = new StringBuilder();
        List<LeaveOfficeRule> leaveOfficeRuleList = new ArrayList<>();
        if (StrKit.isNotEmpty(salaryCalculateRuleListVO.getLeaveOfficeRule())) {
            leaveOfficeRuleList = JSON.parseArray(salaryCalculateRuleListVO.getLeaveOfficeRule(), LeaveOfficeRule.class);
        }
        // 判断工价规则还是劳务费规则(1:工价规则 2：劳务费规则)
        Integer ruleType = salaryCalculateRuleListVO.getRuleType();
        if (!CollectionUtils.isEmpty(leaveOfficeRuleList) && CalculatePayConstant.RULE_TYPE_MAN_HOUR.equals(ruleType)) {
            if (salaryCalculateRuleListVO.getDissatisfyMonth() != null
                    && salaryCalculateRuleListVO.getDissatisfyMonth() == 1) {
                leaveOfficeRuleShow.append("不满月限制。");
            }
            if (salaryCalculateRuleListVO.getEndAstrict() != null
                    && salaryCalculateRuleListVO.getEndAstrict() == 1) {
                EndAstrict endAstrict = JSON.parseObject(salaryCalculateRuleListVO.getEndAstrictJson(), EndAstrict.class);
                String unit = CalculatePayConstant.UNIT_MONTH.equals(endAstrict.getUnit()) ?
                        "月" : CalculatePayConstant.UNIT_DAY.equals(endAstrict.getUnit()) ?
                        "天" : "工时";
                leaveOfficeRuleShow.append("最后阶段限制-最后").append(endAstrict.getNumber()).append(unit).append("。");
            }
            String showType = CalculatePayConstant.SHOW_TYPE_MAN_DAY.equals(salaryCalculateRuleListVO.getLeaveShowType()) ?
                    "计天制-" : "计时制-";
            String unit = CalculatePayConstant.SHOW_TYPE_MAN_DAY.equals(salaryCalculateRuleListVO.getLeaveShowType()) ?
                    "天" : "工时";
            leaveOfficeRuleShow.append("工价计算—").append(showType).append("工价")
                    .append(leaveOfficeRuleList.get(0).getHourAmount()).append("元/").append(unit).append("。");
        } else if (!CollectionUtils.isEmpty(leaveOfficeRuleList) && CalculatePayConstant.RULE_TYPE_COMMISSION.equals(ruleType)) {
            String showType = CalculatePayConstant.SHOW_TYPE_MAN_DAY.equals(salaryCalculateRuleListVO.getLeaveShowType()) ?
                    "按天分润-" : CalculatePayConstant.SHOW_TYPE_MAN_HOUR.equals(salaryCalculateRuleListVO.getLeaveShowType()) ?
                    "工时分润-" : "比例分润-";
            String unit = CalculatePayConstant.SHOW_TYPE_MAN_DAY.equals(salaryCalculateRuleListVO.getLeaveShowType()) ?
                    "元/天" : CalculatePayConstant.SHOW_TYPE_MAN_HOUR.equals(salaryCalculateRuleListVO.getLeaveShowType()) ?
                    "元/工时" : "%工人实发工资";
            leaveOfficeRuleShow.append("渠道分润—").append(showType).append("分润")
                    .append(leaveOfficeRuleList.get(0).getHourAmount()).append(unit).append("。");
        }
        if (Objects.nonNull(leaveRedPacketRule)) {
            String unit = CalculatePayConstant.UNIT_MONTH.equals(leaveRedPacketRule.getUnits()) ?
                    "月" : CalculatePayConstant.UNIT_DAY.equals(leaveRedPacketRule.getUnits()) ?
                    "天" : "工时";
            leaveOfficeRuleShow.append("红包-每满").append(leaveRedPacketRule.getNumber()).append(unit)
                    .append("发放").append(leaveRedPacketRule.getRedPacketAmount()).append("红包。");
        }
        if (Objects.nonNull(salaryCalculateRuleListVO.getSpecialCost())
                && salaryCalculateRuleListVO.getSpecialCost() != 0) {
            BigDecimal specialCost = new BigDecimal(salaryCalculateRuleListVO.getSpecialCost())
                    .divide(new BigDecimal("10000"), 4, BigDecimal.ROUND_DOWN);
            leaveOfficeRuleShow.append("离职倒扣-").append(specialCost).append("元。");
        }
        return leaveOfficeRuleShow.toString();
    }

    /**
     * 保存人事变动
     */
    private void savePersonalEvent(String empId, String des, String event, String eventName, TokenUser tokenUser) {
        EmpInfoDO empInfoDO = empInfoService.selectDOById(empId, tokenUser.getSiteId());
        EmpInfoVO empInfoVO = empInfoDO.to(EmpInfoVO.class);
        personalEventService.autoSave(empInfoVO, tokenUser, des, event, eventName);
    }

    /**
     * 校验工价计算规则是否与原先的相同
     *
     * @return true:需要新增 false:不需要
     */
    private boolean checkRule(String ruleId, SalaryCalculateRuleAddDTO ruleAddDTO, Integer ruleType, TokenUser tokenUser) {

        if (StrKit.isEmpty(ruleId)) {
            return false;
        }
        // 判断是否需要新增工价规则
        SalaryCalculateRuleVO salaryRuleVO = this.selectById(ruleId, tokenUser.getSiteId());
        if (Objects.nonNull(salaryRuleVO) && !CalculatePayConstant.RULE_TYPE_EQUALLY.equals(salaryRuleVO.getRuleType())) {
            // 每小时工价都是空
            if (Objects.isNull(salaryRuleVO.getHourAmount()) && Objects.isNull(ruleAddDTO.getHourAmountDouble())) {

            } else {
                Long hourAmount = salaryRuleVO.getHourAmount();
                if (hourAmount == null) {
                    hourAmount = 0L;
                }
                double v1 = Double.parseDouble(hourAmount + "");
                double v = ruleAddDTO.getHourAmountDouble() * 10000;
                if (v1 != v) {
                    return true;
                }
            }
            // 工价规则
            if (Objects.isNull(salaryRuleVO.getHourAmountRule()) && Objects.isNull(ruleAddDTO.getHourAmountRule())) {

            } else if (!salaryRuleVO.getHourAmountRule().equals(ruleAddDTO.getHourAmountRule())) {
                return true;
            }
            // 红包规则
            if (Objects.isNull(salaryRuleVO.getRedPacketRule()) && Objects.isNull(ruleAddDTO.getRedPacketRule())) {

            } else if (!salaryRuleVO.getRedPacketRule().equals(ruleAddDTO.getRedPacketRule())) {
                return true;
            }
            // 离职规则
            if (Objects.isNull(salaryRuleVO.getLeaveOfficeRule()) && Objects.isNull(ruleAddDTO.getLeaveOfficeRule())) {

            } else if (!salaryRuleVO.getLeaveOfficeRule().equals(ruleAddDTO.getLeaveOfficeRule())) {
                return true;
            }
            // 渠道分润
            if (Objects.isNull(salaryRuleVO.getCommissionRatio()) && Objects.isNull(ruleAddDTO.getCommissionRatio())) {

            } else if (salaryRuleVO.getCommissionRatio().compareTo(new BigDecimal(ruleAddDTO.getCommissionRatio() + "")) != 0) {
                return true;
            }
            // 特殊费用
            if (RULE_TYPE_SERVICE.equals(ruleType)) {
                // 历史的劳务费特殊费用
                Long specialCostLast = salaryRuleVO.getSpecialCost() == null ? 0L : salaryRuleVO.getSpecialCost();
                // 本次的劳务费特殊费用
                Double specialCostDouble = ruleAddDTO.getSpecialCostDouble() == null ? 0L : ruleAddDTO.getSpecialCostDouble();
                specialCostDouble *= 10000;
                Long specialCost = specialCostDouble.longValue();
                if (!specialCostLast.equals(specialCost)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 新建规则
     */
    private SalaryCalculateRuleVO saveRule(SalaryCalculateRuleAddDTO ruleAddDTO, Integer ruleType, TokenUser tokenUser) {
        // 构建规则名称
        String ruleName = empInfoService.buildRuleName(ruleAddDTO, ruleType);
        log.info("薪资档案修改工价规则,构建规则名称:{}", ruleName);
        // 新增工价规则
        ruleAddDTO.setName(ruleName);
        ruleAddDTO.setRuleType(ruleType);
        return this.save(ruleAddDTO, tokenUser);
    }


    private List<EmpInfoListVO> selectEmpInfoListVOByRuleTypeAndSalaryCalculateRuleId(Integer ruleType,
                                                                                      String salaryCalculateRuleId,
                                                                                      TokenUser tokenUser) {
        EmpInfoQuery empInfoQuery = new EmpInfoQuery();
        List<Order> orders = new ArrayList<>();
        orders.add(new Order("gmtCreate", true));
        empInfoQuery.setOrders(orders);
        if (ruleType.equals(CalculatePayConstant.RULE_TYPE_MAN_HOUR) || ruleType.equals(CalculatePayConstant.RULE_TYPE_EQUALLY)) {
            empInfoQuery.setSalaryRuleId(salaryCalculateRuleId);
        } else if (ruleType.equals(CalculatePayConstant.RULE_TYPE_COMMISSION)) {
            empInfoQuery.setServiceFeeRuleId(salaryCalculateRuleId);
        }
        List<EmpInfoListVO> empInfoListVOList = empInfoService.select(empInfoQuery, tokenUser);
        // 根据手机号过滤
        empInfoListVOList = empInfoListVOList.stream().
                collect(Collectors.collectingAndThen(Collectors.toCollection(() ->
                        new TreeSet<>(Comparator.comparing(EmpInfoListVO::getPhone))), ArrayList::new));
        // 过滤掉离职的员工信息
        empInfoListVOList.removeIf(empInfoListVO -> EmpInfoStatus.HAS_QUIT.getValue().equals(empInfoListVO.getStatus()));
        return empInfoListVOList;
    }


    /**
     * 根据查询参数，构建example
     *
     * @param salaryCalculateRuleQuery 查询参数
     * @param siteId                   所属站点id
     * @return example
     */
    private Example buildExample(SalaryCalculateRuleQuery salaryCalculateRuleQuery, String siteId) {
        Example example = new Example(SalaryCalculateRuleDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        if (salaryCalculateRuleQuery.getSalaryCalculateRuleGroupId() != null) {
            example.and().andEqualTo("salaryCalculateRuleGroupId", salaryCalculateRuleQuery.getSalaryCalculateRuleGroupId());
        }
        if (salaryCalculateRuleQuery.getName() != null) {
            example.and().andLike("name", "%" + salaryCalculateRuleQuery.getName() + "%");
        }
        if (salaryCalculateRuleQuery.getTimeType() != null) {
            example.and().andEqualTo("timeType", salaryCalculateRuleQuery.getTimeType());
        }
        if (salaryCalculateRuleQuery.getRuleType() != null) {
            if (salaryCalculateRuleQuery.getRuleType().equals(CalculatePayConstant.RULE_TYPE_COMMISSION)) {
                example.and().andEqualTo("ruleType", salaryCalculateRuleQuery.getRuleType());
            } else {
                example.and().andNotEqualTo("ruleType", CalculatePayConstant.RULE_TYPE_COMMISSION);
            }
        }
        if (salaryCalculateRuleQuery.getShowType() != null) {
            example.and().andEqualTo("showType", salaryCalculateRuleQuery.getShowType());
        }
        if (salaryCalculateRuleQuery.getHourAmount() != null) {
            example.and().andEqualTo("hourAmount", salaryCalculateRuleQuery.getHourAmount());
        }
        if (salaryCalculateRuleQuery.getHourAmountRule() != null) {
            example.and().andEqualTo("hourAmountRule", salaryCalculateRuleQuery.getHourAmountRule());
        }
        if (salaryCalculateRuleQuery.getRedPacketRule() != null) {
            example.and().andEqualTo("redPacketRule", salaryCalculateRuleQuery.getRedPacketRule());
        }
        if (salaryCalculateRuleQuery.getLeaveOfficeRule() != null) {
            example.and().andEqualTo("leaveOfficeRule", salaryCalculateRuleQuery.getLeaveOfficeRule());
        }
        // 排序
        ExampleKit.setExampleOrder(example, salaryCalculateRuleQuery.getOrders());
        return example;
    }
}




